home *** CD-ROM | disk | FTP | other *** search
- PAGE 59, 132
-
- TITLE MsHelper -- Windowing help module for VT100 emulation on IBM PC
-
- ; Update 6 Jan 86
-
- IF1
- %OUT >> Starting pass 1
- ELSE
- %OUT >> Starting pass 2
- ENDIF
-
- PUBLIC Helper
- .SALL
-
- ;***************************************************************************
- ; *Definitions* ...
-
- ; Global defs
-
- INCLUDE MsDefs.H
-
- DataS SEGMENT PUBLIC 'DataS'
-
- EXTRN Which_page:BYTE, Screen_flags:BYTE
- EXTRN Video_page_addresses:WORD, m7171:BYTE
- EXTRN Force_mono:BYTE, m7171:BYTE
-
- Screen EQU 10h ; BIOS screen call
- Kb EQU 16h ; BIOS keyboard call
-
- Old_7171_mode DB ? ; If we were here before, which mode was it?
-
- ; Screen stuff
-
- Number_of_columns EQU 80 ; Width in characters
- Number_of_rows_PC EQU 25 ; Length in rows including mode line
- Number_of_chars_on_PC_screen EQU Number_of_columns*Number_of_rows_PC
- ; Number of chars in IBM screen
-
- ; Flag set in Screen_flags
-
- Screen_changed EQU 8 ; Data on more than one line changed
-
- Saved_mode_line DW Number_of_columns DUP (?) ; Saved image of Mode line
-
- ; Scan codes for keys we have predefined ...
-
- Escape_key EQU 1
- Space_key EQU 57
- F6_key EQU 64
- ALT_F6_key EQU 109
- End_key EQU 79
- Down_key EQU 80
- PgDn_key EQU 81
- Left_key EQU 75
- Right_key EQU 77
- Home_key EQU 71
- Up_key EQU 72
- PgUp_key EQU 73
-
- Characters LABEL BYTE
- DB Space_key, Escape_key, F6_key
- DB Home_key, End_key, PgUp_key
- DB PgDn_key, Up_key, Down_key
- DB Left_key, Right_key, ALT_F6_key
- N_Characters EQU $-Characters
- Actions LABEL WORD
- DW CHK_bye, CHK_bye, CHK_bye
- DW Do_Home, Do_End, Do_PgUp
- DW Do_PgDn, Do_Up, Do_Down
- DW Do_Up, Do_Down, CHK_bye
- DW Do_boop
-
- PUBLIC Help_file_name, Characters, Actions
-
- Help_file_name LABEL BYTE
- Program_name
- DB '.HLP',0 ; Name of our help file
-
- Help_file_7171 LABEL BYTE
- Program_name
- DB '.H71',0 ; Name of our help file on IBM 7171
-
- No_memory DB ' *** Not enough memory for HELP -- Press any key to continue ***$'
-
- Cant_find_file DB ' ***** Missing '
- Program_name
- DB '.HLP -- Press any key to continue *****$'
-
- Cant_find_7171 DB ' ***** Missing '
- Program_name
- DB '.H71 -- Press any key to continue *****$'
-
- DataS ENDS
-
-
- ; Dummy segment for allocated memory
-
- HAlloc SEGMENT AT 0
-
- First_line DW ? ; Ptr to first line in database
- Last_line DW ? ; Ptr to last line in database
- Last_top_line DW ? ; Ptr to line on top of last frame
- Current_line DW ? ; Ptr to line currently at top of window
-
- Which_row DW ? ; Which row are we writing in?
-
- PUBLIC Our_Image, Our_cursor, Which_row, Current_line, First_line
-
- Our_cursor DW ? ; Our position
- Our_Image DW Number_of_chars_on_PC_screen DUP (?) ; Our buffer
-
- PUBLIC Help_database, Help_file_buffer,End_HAlloc
-
- Zero DB ? ; Make backward searches stop here ...
- Help_database DB 300*74 DUP (?) ; Where we store the help text
-
- Help_file_buffer DB 2048 DUP (?) ; Buffer for reading Help file from disk
-
- End_HAlloc LABEL BYTE ; Ptr to end of what we need
-
- HAlloc ENDS
-
-
- Code SEGMENT PUBLIC
-
- EXTRN Put_Screen:NEAR, Get_Screen_Segment:NEAR, Boop:NEAR
- EXTRN SPath:NEAR, Check_table:NEAR, Do_mode_line:NEAR
- EXTRN Get_memory_block:NEAR, PutErr_PC:NEAR, Screen_Image_ptr:DWORD
- EXTRN Which_card:BYTE, Mode_line_ptr:DWORD
-
- ASSUME CS:Code, DS:DataS, ES:DataS
-
- Normal_ds DW ? ; Ptr back to ds on entry
- HAlloc_ptr DW ? ; Address of HAlloc segment
-
- PUBLIC HFlags
-
- HFlags DB 0 ; Internal flags, kept in code segment
- ; for easy access
-
- Bye_bye EQU 1 ; Flag to leave
- Been_here EQU 2 ; Already did once-only initialization
-
- Helper PROC
-
- and HFlags, NOT Bye_bye ; Flag that we aren't leaving yet
-
- test HFlags, Been_here ; Been here before?
- jz HLP_go ; No ...
-
- ; We have been here before, but maybe with the wrong help file ...
-
- mov al, m7171 ; Pick up current 7171 mode
- cmp al, Old_7171_mode ; Same as last time?
- je HLP_1 ; Same, just display our buffer
-
- ; We have been here before, so we already have memory allocated ...
- ; We just need to reload the database
-
- mov ax, HAlloc_ptr ; Reuse old memory
- jmp SHORT H_ok ; Join common code
-
- HLP_go:
-
- ; First, get some memory to work in
-
- ; *** The silly assembler won't let me do this, saying
- ; Constant was expected
- ; or something like that ...
-
- ; mov bx, (OFFSET End_HAlloc+15) SHR 4 ; Lowest location we don't use,
- ; round up to next higher paragraph,
- ; then convert to number of paragraphs
-
- mov bx, OFFSET End_HAlloc+15 ; Round up to next paragraph
- mov cl, 4 ; Shift count
- shr bx, cl ; Shift to get number of paras we need
-
- call Get_memory_block ; Get a memory block of the right size
- jnc H_OK ; Ok so far ...
-
- mov dx, OFFSET No_memory ; Complain
- jmp Do_mode_line_error ; Display noisy error message, wait for
- ; keystroke, then exit, restoring
- ; clobbered mode line
-
- H_OK: mov HAlloc_ptr, ax ; Save the address of our block
-
- mov bx, ds ; Set up ptr back to ds
- mov Normal_ds, bx ; Save ptr back to old one
-
- ; Switch to HAlloc segment ...
-
- mov ds, ax ; Point ds to HAlloc
- mov es, ax ; es also ...
-
- ASSUME ds:HAlloc, es:HAlloc ; Tell assembler we have a new ds and es
-
- mov Zero, 0 ; Store a zero
-
- call Build_Help_database ; Build the database
- test HFlags, Bye_bye ; Time to leave?
- jz HLP_0 ; Not yet
-
- ; *** Properly speaking, we really ought to release the memory we
- ; were just allocated, since we can't use it ... maybe later ***
-
- jmp Back_to_normal_ds ; Oh well ...
-
- HLP_0: or HFlags, Been_here ; Flag for later
-
- call Back_to_normal_ds
-
- ASSUME ds:DataS, es:DataS
-
- mov al, m7171 ; Pick up current 7171 mode
- mov Old_7171_mode, al ; Store it for later test
-
- call Use_our_own_ds
-
- ASSUME ds:HAlloc, es:HAlloc
-
- jmp SHORT HLP_1a
-
- ASSUME ds:DataS, es:DataS
-
- HLP_1: call Use_our_own_ds ; Switch to HAlloc segment
-
- ASSUME ds:HAlloc, es:HAlloc
-
- HLP_1a: call Build_box ; Build outline / background for Help window
-
- mov ax, First_line ; Address of start at Help text
- mov Current_line, ax ; Set up as current position
-
- HLP_2: call Fill_frame ; Get frame ready
- call Do_the_screen ; Display this frame
-
- call Check_keystrokes ; See what to do next
- test HFlags, Bye_bye ; Time to leave?
- jz HLP_2 ; No, go update the frame
-
- jmp Back_to_normal_ds ; Done here
-
-
- PUBLIC Bombed
-
- ASSUME ds:DataS, es:DataS
- Bombed: call Boop ; Bombed, make a noise
- or HFlags, Bye_bye ; Go home
- ret
- ASSUME ds:HAlloc, es:HAlloc
-
-
- PUBLIC Build_Help_database
-
- Build_Help_database:
-
- call Back_to_normal_ds ; Need old ds to open file
-
- ASSUME ds:DataS, es:DataS
-
- mov ax, OFFSET Help_file_name ; Name of file to get
- cmp m7171, 0 ; In 7171 mode?
- je BUI_0
-
- mov ax, OFFSET Help_file_7171 ; Name of the other file
-
- BUI_0: call spath ; Search path for file, DSK: first
- jnc BUI_ok ; Got it, go work with it
-
- mov dx, OFFSET Cant_find_file ; Complain
- cmp m7171, 0 ; In 7171 mode?
- je BUI_1
-
- mov dx, OFFSET Cant_find_7171 ; Complain about missing 7171 file
-
- BUI_1: call Do_mode_line_error ; Wait for a key
- jmp Use_our_own_ds ; Reset ds and return NG
-
- BUI_ok:
- mov dx, ax ; Copy ptr to name to dx
- mov ax, (Open2*100h) + 0 ; Open file for input
- int DOS ; Try to open the file
- jc Bombed ; Huh?
-
- mov bx, ax ; Copy handle to bx
-
- call Use_our_own_ds ; Back to our own version
-
- ASSUME ds:HAlloc, es:HAlloc
-
- mov di, OFFSET Help_database ; Ptr to start of our database
- mov First_line, di ; Save ptr to start for later
- mov Current_line, di ; Also a ptr for making Last_line later
- cld ; Build forwards
-
- BUI_disk_read:
- mov ah, ReadF2 ; Code to read from file, handle still in bx
- mov cx, SIZE Help_file_buffer ; Number of characters to try for
- mov dx, OFFSET Help_file_buffer ; Where to put them
- int DOS ; Read from the help file
- jc BUI_finish ; Stop on error
-
- or ax, ax ; Check for zero bytes read
- jz BUI_finish ; Hit EOF, go finish it up
-
- mov cx, ax ; Byte count for this record
- inc cx ; We decr once too many times
- mov si, OFFSET Help_file_buffer ; Ptr to buffer
-
- BUI_lp: loop BUI_next_char ; If more chars, go get one
- jmp SHORT BUI_disk_read ; Buffer is empty, try to refill it
-
- BUI_next_char:
- lodsb ; Get the next byte
-
- cmp al, CtlZ ; Control-Z?
- jl BUI_control ; Less, check for control char
- je BUI_lp ; Ignore control Z
-
- stosb ; Store the char
- jmp BUI_lp ; Go do another one
-
- BUI_control:
- cmp al, Lf ; Line feed?
- jne BUI_lp ; No
-
- sub al, al ; Make a zero
- stosb ; Tie off the last line
-
- mov ax, Current_line ; Pick up trailing ptr
- mov Last_line, ax ; Assume it's the last line, for now
- mov Current_line, di ; Update trailing ptr for next round
-
- jmp BUI_lp ; Go get another character
-
- BUI_finish:
- sub al, al ; Make a zero
- mov cx, 25 ; Make several blank lines after help database
- rep stosb ; Write a string of zeros
-
- mov ah, 3eh ; Code to close a file
- int DOS ; Close the file
-
- mov di, Last_line
- mov Current_line, di
- mov cx, Len - 3 ; Maximum number of lines to move
- call PgUp_lp ; Get a new DI pointing to proper line
- mov Last_top_line, di ; Save for later
-
- ret ; Done here
-
- PUBLIC Build_box
-
- Build_box:
-
- cld ; Forwards
- mov di, OFFSET Our_Image ; Our own buffer
- mov cx, Number_of_chars_on_PC_screen ; How many chars
- lds si, Screen_Image_ptr ; Addr of copy of screen at entry
- rep movsw ; Install incoming screen as background
- push es ; Our segment
- pop ds ; Set up ds again
-
- Wid=Number_of_columns-(2*Help_window_left) ; How many columns
- Len=Number_of_rows_PC-(2*Help_window_top) ; How many rows
-
- Color_attr=1eh ; Bright yellow on blue
- Mono_attr=70h ; Black on white
-
-
- %OUT >> About half way through source file
-
-
- Upper_left=218 ; Box drawing chars
- Upper_right=191
- Lower_left=192
- Lower_right=217
- Horizontal=196
- Vertical=179
-
- mov ax, Help_window_top ; Row number of top of window
- mov Which_row, ax ; Save it for later
- call Make_new_ptr ; Get a new DI
-
-
- ; Set up proper attribute based on card type
-
- mov bh, Mono_attr ; Assume mono
- call Back_to_normal_ds
- ASSUME ds:DataS, es:DATAS
-
- cmp Force_mono, 0 ; Are we stuck with mono?
- jne MON_0 ; Yes
-
- call Get_Screen_Segment
- cmp ax, 0b000h ; Mono?
- je MON_0 ; It is, go use it
-
- mov bh, Color_attr ; Color, use it instead
-
- PUBLIC MON_0
-
- MON_0: mov ah, bh ; Install in ah
- call Use_our_own_ds
- ASSUME ds:HAlloc, es:HAlloc
-
- ; Do top row of help window
-
- mov al, Upper_left
- stosw
-
- mov al, Horizontal
- mov cx, Wid - 2
- rep stosw
-
- mov al, Upper_right
- stosw
-
- inc Which_row ; Bump to next row
- call Make_new_ptr ; Point to it
-
- ; Do the middle rows of the help window
-
- mov cx, Len - 2 ; Number of rows to do
-
- PUBLIC LP_1
-
- LP_1: push cx
-
- mov al, Vertical
- stosw
-
- mov al, Space
- mov cx, Wid - 2
- rep stosw
-
- mov al, Vertical
- stosw
-
- pop cx
-
- inc Which_row ; Bump to next row
- call Make_new_ptr ; Point to it
-
- loop LP_1
-
- ; Do bottom row of help window
-
- mov al, Lower_left
- stosw
-
- mov al, Horizontal
- mov cx, Wid - 2
- rep stosw
-
- mov al, Lower_right
- stosw
-
- mov ax, (100h * Help_window_top) + Help_window_left ; New position
- mov Our_cursor, ax ; Set it for Put_Screen
-
- ret
-
-
- ; Set up a pointer to this row
-
- PUBLIC Make_new_ptr
-
- Make_new_ptr:
- push ax ; Save reg
- mov ax, Which_row ; Row number of topmost row
- mov bh, 2 * Number_of_columns ; Convert to bytes
- mul bh
- add ax, (2 * Help_window_left) + OFFSET Our_Image ; Point to our
- ; image, proper column
- mov di, ax ; Set up as destination
- pop ax ; Restore reg
- ret ; Go use it
-
-
- PUBLIC Fill_frame
-
- Fill_frame:
- cld ; Build forwards
- mov ax, Help_window_top + 1 ; Row number to start writing to
- mov Which_row, ax ; Save it
- call Make_new_ptr ; Get a new DI
- add di, 4 ; Skip over border, and another space
-
- mov si, Current_line ; Start at current position in help text
- mov cx, Len - 2 ; Number of rows to write
-
- FIL_lp_outer:
- push cx ; Save outer loop counter
- mov cx, Wid - 4 ; Number of chars we can fit in a line
-
- FIL_lp_inner:
- lodsb ; Pick up the next byte
- or al, al ; Check for zero
- jnz FIL_inner_bot ; Char is ok, use it
-
- dec si ; Back up to re-read the zero byte
- mov al, Space ; Pad character
-
- FIL_inner_bot:
- stosb ; Store this char
- inc di ; Skip attribute
- loop FIL_lp_inner ; Go do another char
-
- ; End of inner loop, skip chars until we hit a zero byte
-
- FIL_end_of_inner:
- lodsb ; Pick up the next byte
- or al, al ; Is it zero?
- jnz FIL_end_of_inner ; Skip chars until we hit a zero
-
- inc Which_row ; Move to next row
- call Make_new_ptr ; Get a new DI
- add di, 4 ; Skip over border and first column
-
- pop cx ; Restore outer loop counter
- loop FIL_lp_outer ; Go try for another line
-
- ret
-
-
- PUBLIC Check_keystrokes
-
- Check_keystrokes:
-
- call Back_to_normal_ds
- call Do_mode_line ; Update the mode line
- call Use_our_own_ds
-
- mov di, OFFSET Our_image + (24 * 160) ; Where our copy is
- mov cx, Number_of_columns ; Size of mode line
- lds si, Mode_line_ptr ; Point to real mode line
- ASSUME ds:Nothing
- cld ; Forwards
- rep movsw ; Copy the mode line to our buffer
- push es ; Restore ds
- pop ds
- ASSUME ds:HAlloc
-
- call Do_the_screen ; Install image
-
- mov ah, 1 ; Code to see if a char is ready
- int Kb ; Have BIOS tell us
- jz Check_keystrokes ; None, waste time on mode line
-
- sub ah, ah ; Zero is code to read the char
- int Kb ; Have BIOS get it for us
-
- call Back_to_normal_ds ; Check_Table requires normal ds
- mov al, ah ; Copy scan code to al
- mov bx, OFFSET Actions ; Action table
- mov cx, N_Characters ; Number of scan codes to check
- mov dx, OFFSET Characters ; The character table
- jmp Check_Table ; Go dispatch to the right routine
-
- PUBLIC Do_the_screen, Do_boop
-
- Do_the_screen:
- mov bx, OFFSET Our_Image ; Set ptr to our screen
-
- mov ax, Normal_ds ; Put_Screen likes normal ds
- mov ds, ax
- ASSUME ds:DataS
- or Screen_flags, Screen_changed ; Flag that Put_Screen has to work
- call Put_Screen ; Update screen
-
- push es ; Reset ds
- pop ds
- ASSUME ds:HAlloc
- ret ; Done here
-
- Do_boop:
- call Back_to_normal_ds ; Boop requires this
- call Boop ; Give low beep
- call Use_our_own_ds ; Ours again
- jmp Check_keystrokes ; Try again
-
- Do_Home:
- call Use_our_own_ds ; Ours again
- mov di, First_line ; Button to go to first line
- cmp di, Current_line ; Are we on it already?
- je Do_boop ; Yeah, complain for consistency
-
- mov Current_line, di ; Otherwise, go to first line
- ret
-
- Do_End: call Use_our_own_ds ; Ours again
- mov di, Last_top_line ; Button to go to last frame line
- cmp di, Current_line ; Are we on it already?
- je Do_boop ; Yeah, complain for consistency
-
- mov Current_line, di ; Otherwise, go to it
- ret
-
- Do_PgUp:
- call Use_our_own_ds ; Ours again
- mov di, Current_line ; Line we are on
- cmp di, First_line ; First line we can be on
- je Do_boop ; Can't go up
-
- mov cx, Len - 3 ; Maximum number of lines to move
- jmp SHORT PgUp_lp
-
- Do_PgDn:
- call Use_our_own_ds ; Ours again
- mov di, Current_line ; Line we are on
- cmp di, Last_line ; Last line we can be on
- je Do_boop ; Can't go down
-
- mov cx, Len - 3 ; Maximum number of lines to move
- jmp SHORT PgDn_lp
-
- Do_Up: call Use_our_own_ds ; Ours again
- mov di, Current_line ; Line we are on
- cmp di, First_line ; First line we can be on
- je Do_boop ; Can't go up
- jmp SHORT Up
-
- Do_Down:
- call Use_our_own_ds ; Ours again
- mov di, Current_line ; Line we are on
- cmp di, Last_line ; Last line we can be on
- je Do_boop ; Can't go down
- jmp SHORT Down
-
- CHK_bye:
- call Use_our_own_ds ; Ours again
- or HFlags, Bye_bye ; Flag the exit
- ret ; Done here
-
- PgUp_lp:
- push cx ; Other routine clobbers this
- call Up ; Try to move up
- mov di, Current_line ; Line we are on
- cmp di, First_line ; First line we can be on
- je CHK_pop ; Can't go up, pop reg and return
- pop cx ; Restore reg
- loop PgUp_lp ; Do the rest
- ret ; Done here
-
- PgDn_lp:
- push cx ; Other routine clobbers this
- call Down ; Try to move down
- mov di, Current_line ; Line we are on
- cmp di, Last_line ; Last line we can be on
- je CHK_pop ; Can't go up, pop reg and return
- pop cx ; Restore reg
- loop PgDn_lp ; Do the rest
- ret ; Done here
-
- Down: mov cx, 80 ; Max number of chars to scan
- sub al, al ; Make a zero
- cld ; Forwards
- repne scasb ; Go looking for a zero byte
-
- mov Current_line, di ; Now pointing to beginning of next line
- ret
-
- Up: sub di, 2 ; Skip back over terminator
- mov cx, 80 ; Max number of chars to scan
- sub al, al ; Make a zero
- std ; Backwards
- repne scasb ; Go looking for a zero byte
-
- add di, 2 ; Skip forwards over terminator
- mov Current_line, di ; Now pointing to beginning of previous line
- ret
-
- CHK_pop:
- pop cx ; Restore reg
- ret
-
- Back_to_normal_ds:
- push ax ; Save reg
- mov ax, Normal_ds ; Pick up addr of DataS segment
- mov ds, ax ; Copy to ds
- mov es, ax ; and es
- pop ax ; Restore reg
- ret ; and return
-
- ASSUME ds:DataS, es:DataS
-
- Use_our_own_ds:
- push ax ; Save reg
- mov ax, HAlloc_ptr ; Pick up addr of HAlloc segment
- mov ds, ax ; Copy to ds
- mov es, ax ; and es
- pop ax ; Restore reg
- ret ; and return
-
- Helper ENDP
-
- Do_mode_line_error PROC
-
- call Save_mode_line ; Ask for a save
- call PutErr_PC ; Play with mode line
- call Bombed ; Make noise
- sub ah, ah ; Code to read a character
- int Kb ; Wait until user hits key
- jmp Restore_mode_line ; Ask for a restore, ret from there
-
- Do_mode_line_error ENDP
-
-
- ; Save the mode line for later restoral
-
- Save_mode_line PROC
-
- push ds ; Save ds
- call Get_address ; Get new ds into ax
- mov ds, ax ; Store the new seg addr
- mov si, (Number_of_rows_PC-1)*2*Number_of_columns ; Offset of line 25
- mov di, OFFSET Saved_mode_line ; Where to copy it
- mov cx, Number_of_columns
- cld ; Forwards
- rep movsw ; Save the line
- pop ds ; Restore ds
- ret
-
- Save_mode_line ENDP
-
-
- ; Restore the mode line
-
- Restore_mode_line PROC
-
- push es ; Save es
- call Get_address ; Get new es into ax
- mov es, ax ; Store the new seg addr
- mov si, OFFSET Saved_mode_line ; Where copy is
- mov di, (Number_of_rows_PC-1)*2*Number_of_columns ; Offset of line 25
- mov cx, Number_of_columns
- cld ; Forwards
- rep movsw ; Restore the line
- pop es ; Restore es
- ret
-
- Restore_mode_line ENDP
-
-
- ; Get address of segment of currently-displayed video page
-
- Get_address PROC
-
- mov ax, 0B000h ; Mono, maybe
- cmp Which_card, 0 ; Is it?
- je Go_back ; Yes
-
- sub bh, bh ; Zero high half of bx
- mov bl, Which_page ; The page we are on in the color card
- shl bx, 1 ; Double for word offset into table
- mov ax, Video_page_addresses[bx] ; Pick up the address for the page
-
- Go_back:
- ret
-
- Get_address ENDP
-
- Code ENDS
-
- END
-